#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
#
# Description: configure.ac
#   Autonconf produce a ./configure from this file
#   that's used to discover various programs/dependencies
#   usage: autoconf
#
# Authors: paul_c alex_joni jepler
# License: GPL Version 2
# System: Linux
#
# Copyright (c) 2004 All rights reserved.
#
# Last change:
# This file is released under GPL, refer to docs/README for details
#
# This file is adapted to replace the old ./configure script
# therefor it includes parts of that script

##############################################################################
# Section 1                                                                  #
# Autoconf initialisation                                                    #
##############################################################################

AC_PREREQ(2.53)
AC_INIT([Machinekit-HAL],
        [m4_normalize(esyscmd(cat ../VERSION))],
        [https://github.com/machinekit/machinekit-hal/issues])
if test "$srcdir" != "."; then
    AC_MSG_ERROR([Building outside of srcdir is not supported])
fi

AC_ARG_WITH(python,
    [  --with-python=<path>                    Specify the Python interpreter],
    [
        PYTHON=$withval
    ],[
        PYTHON=python3
    ])
AC_PATH_PROG(PYTHON,$PYTHON,"none")
if test $PYTHON = "none"
then
    AC_MSG_ERROR([python not found])
fi

# Cython Python Bindings generator
# 0.19.1 is the version currently in wheezy-backports
AC_PROG_CYTHON(0.19.0)
if test "$CYTHON" = "false"; then
    AC_MSG_ERROR([not found])
fi
AC_SUBST([CYTHON], [$CYTHON])


AC_MSG_CHECKING(build toplevel)
BUILD_TOPLEVEL="$(cd ..; pwd -P)"
AC_MSG_RESULT($BUILD_TOPLEVEL)

AC_CONFIG_HEADER(config.h)

# Support some of the standard configure options for directories
AC_PREFIX_DEFAULT(run-in-place)

AC_MSG_CHECKING(installation prefix)
if test "x$prefix" = "xNONE"; then
  RUN_IN_PLACE=yes
  AC_MSG_RESULT(run in place)
  prefix=${BUILD_TOPLEVEL}
else
  RUN_IN_PLACE=no
  AC_MSG_RESULT($prefix)
fi
AC_SUBST(AUTODIRS)

# internationalisation package name:
PACKAGE="machinekit"
AC_SUBST([PACKAGE])

if test -f ../VERSION; then
    HALVERSION="$(cat ../VERSION)"
else
    HALVERSION="Undetermined"
fi
AC_SUBST([HALVERSION])

AC_PATH_PROG(GREP, grep)
AC_PATH_PROG(EGREP, egrep)

AC_PROG_CC
AC_SUBST([CROSS_COMPILING],[$cross_compiling])
dnl Put a plausible default for CC_FOR_BUILD in Makefile.inc.in
if test "$cross_compiling" = yes; then
    AC_PATH_PROGS(CC_FOR_BUILD, gcc cc)
else
    AC_SUBST(CC_FOR_BUILD,$CC)
fi

AC_PROG_CXX
AC_PROG_CPP()
AC_CHECK_TOOL(OBJCOPY, objcopy)
AC_CHECK_TOOL(LD, ld)

# tools for correct cross-building; this sets $host (the target
# system) to e.g. x86_64-unknown-linux-gnu
AC_CANONICAL_HOST  # $host, host_cpu, host_vendor, and host_os
AC_CANONICAL_BUILD  # $build, build_cpu, build_vendor, and build_os

# locate pkg-config, including cross-compiler variations
if test "$cross_compiling" = yes; then
   AC_CHECK_TOOL(PKG_CONFIG, pkg-config)
else
   # The multi-arch version can choke on non-multi-arch packages, since it
   # (intentionally) doesn't look in `/usr/lib/pkgconfig`.
   AC_CHECK_PROGS(PKG_CONFIG, pkg-config)
   dnl Avoid PKG_CHECK_MODULES re-checking
   ac_cv_env_PKG_CONFIG_set=set
fi
AC_CONFIG_MACRO_DIR(/usr/share/aclocal)


##############################################################################
# Section 2                                                                  #
# RealTime checking                                                          #
# Subsection 2.2 - documentation of threads variables to be configured       #
# Subsection 2.3 - misc basic features:  platform, parport I/O, etc.         #
# Subsection 2.4 - kernel detection and RT capability probing                #
# Subsection 2.5 - thread style configuration                                #
# Subsection 2.6 - userland PCI driver configuration                         #
# Subsection 2.7 - pass configuration into config.h, Makefile.inc.in, etc.   #
##############################################################################


##############################################################################
# Subsection 2.2                                                             #
# Variable documentation                                                     #
#                                                                            #
# Here the various Makefile variables and CPP macros generated by this       #
# script are documented                                                      #
##############################################################################

#--------------------------------------------------------#
# Makefile variables                                     #

# RT system Makefile variables defined by configure:
#
# <THREADS_SYSTEM>_THREADS_RTS
#
# a script like /usr/realtime/foo-config, which can be used to extract
# c or ld flags specific for the thread system.
#
# HAVE_<THREADS_SYSTEM>_THREADS
#
# 'yes' or 'no' depending on whether the thread system was able to be
# configured
#
# <THREADS_SYSTEM>_RTFLAGS
#
# list of CFLAGS specific to threads systems; some flavors
# determine this with <THREADS_SYSTEM>_THREADS_RTS --cflags
#
# <THREADS_SYSTEM>_LDFLAGS
#
# list of LDFLAGS specific to the threads system; also obtained partly
# from <THREADS_SYSTEM>_THREADS_RTS --ldflags
#
# path name to a Module.symvers file needed by kbuild
#
# math-related CFLAGS used in RTAPI compiles; partly obtained by
# <THREADS_SYSTEM>_THREADS_RTS

#--------------------------------------------------------#
# config.h macros                                        #
#
# $(THREADS) is used to select the RTAPI_FLAVOR_ID, passed in a CFLAG
# as -DRTAPI_FLAVOR_ID=$(RTAPI_FLAVOR_ID), then used to select the
# appropriate flavor macros from config.h.
#
# flavor macros from config.h, set appropriately for each '$(MAKE)
# threads=<flavor> modules' run:

# GIT_VERSION
#
# a string containing the content of src/VERSION, git branch name,
# and shortened SHA, valid at the time when configure was run.
# generated by running scripts/get-version-from-git at configure time.
# Example:
#
# define GIT_VERSION "v2.6.0~pre~make-clean-check~0255c8c"

# GIT_CONFIG_SHA
#
# a string containing the shortened SHA, valid at the time when configure was run.
# generated by running scripts/get-git-sha at configure time.
# Example:
#
# GIT_CONFIG_SHA "0255c8c"
# the Makefile runs the same script, and adds -DGIT_BUILD_SHA=\"'$(GIT_BUILD_SHA)'\"
# to CFLAGS for logging or a runtime check

# ------------ drivers: build or dont build -------------
#
# BUILD_DRIVERS
#
# ./configure will attempt to configure driver building unless
# explicitly disabled with '--disable-drivers'.
#
# reflected in config.h as follows:
# /* build hardware drivers */
# #define BUILD_DRIVERS /**/
#


# USE_PORTABLE_PARPORT_IO="no"
#
# Parport: on x86 PC platform, we can use either use
# direct inb/outb or the slower but portable ppdev ioctl
#
# reflected in config.h as follows:
# /* build hardware drivers */
# #define USE_PORTABLE_PARPORT_IO /**/

# PLATFORM
# TARGET_PLATFORM_PC
# TARGET_PLATFORM_SOCFPGA
# TARGET_PLATFORM_BEAGLEBONE
# TARGET_PLATFORM_H3
# TARGET_PLATFORM_CHIP
# TARGET_PLATFORM_RASPBERRY
# TARGET_PLATFORM_ZEDBOARD
#
# Platforms. set by --with-platform-{pc,beaglebone,h3,chip,socfpga,raspberry,zedboard}
# see Section 2.3 to enable other platforms, and 2.7 to AC_DEFINE it

# xenomai equivalent of pkg-config
XENO_CONFIG=

# note to mah: dont forget debian/configure FIXME


##############################################################################
# Subsection 2.3                                                             #
# Configure several basic features:                                          #
# - some etc/machinekit/machinekit.ini  values                                 #
# - the MKUUID instance UUID                                                 #
# - Platform (PC, Raspberry Pi, CHIP, BeagleBone, H3 SoC, SocFpga, Zedboard) #
# - Common shared memory driver                                              #
# - Parport I/O mode (portable or inb/outb)                                  #
##############################################################################

# Platform:
#
# By default, build all platforms applicable to the $host arch
#
# If any --with-platform-* provided, only build for that platform if
# $host arch applies
#
# If any --without-platform-* provided, build everything *except* that
# platform, if $host arch applies

platform_specified=false
# Status messages
arch_enab_msg="default enabled for this architecture"
arch_disab_msg="disabled for this architecture"
cmdl_enab_msg="enabled on command line"
cmdl_disab_msg="disabled on command line"
cmdl_notspec_msg="not specified on command line"

AC_CANONICAL_HOST

# Needed for PCI access
AC_CHECK_HEADERS([sys/io.h],[HAVE_SYS_IO=yes], [HAVE_SYS_IO=no])
AC_SUBST([HAVE_SYS_IO])

AC_ARG_WITH(platform-pc,
    [AS_HELP_STRING(
        [--with-platform-pc],
	[Build for PC platform (default for x86 arch)])],
    [
        case $with_platform_pc in
	    (y*)
	    	TARGET_PLATFORM_PC=true
		platform_specified=true
		platform_pc_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_PC=false
		platform_pc_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (x86_64)
	        ARCH_CFLAGS="-m64"
		TARGET_PLATFORM_PC=unk
		;;
	    (i?86)
	        ARCH_CFLAGS="-m32"
		TARGET_PLATFORM_PC=unk
		;;

	    (*)
	        TARGET_PLATFORM_PC=false
		platform_pc_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-socfpga,
    [AS_HELP_STRING(
        [--with-platform-socfpga],
	[Build for Socfpga platform (default for ARM arch)])],
    [
        case $with_platform_socfpga in
	    (y*)
	    	TARGET_PLATFORM_SOCFPGA=true
		platform_specified=true
		platform_socfpga_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_SOCFPGA=false
		platform_socfpga_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*|aarch64)
	        TARGET_PLATFORM_SOCFPGA=unk
		;;
	    (*)
	        TARGET_PLATFORM_SOCFPGA=false
		platform_socfpga_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-beaglebone,
    [AS_HELP_STRING(
        [--with-platform-beaglebone],
	[Build for Beaglebone platform (default for ARM arch)])],
    [
        case $with_platform_beaglebone in
	    (y*)
	    	TARGET_PLATFORM_BEAGLEBONE=true
		platform_specified=true
		platform_beaglebone_reason="$cmdl_enab_msg"
		if test $host_cpu = arm; then
		    # see https://github.com/machinekit/machinekit/issues/629
		    ARCH_CFLAGS="-march=armv7-a -mtune=cortex-a8"
		    ARCH_CFLAGS="$ARCH_CFLAGS -mfloat-abi=hard -mfpu=neon -ffast-math"
		fi
		;;
	    (*)
	    	TARGET_PLATFORM_BEAGLEBONE=false
		platform_beaglebone_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*)
	        TARGET_PLATFORM_BEAGLEBONE=unk
		;;
	    (*)
	        TARGET_PLATFORM_BEAGLEBONE=false
		platform_beaglebone_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-h3,
    [AS_HELP_STRING(
        [--with-platform-h3],
	[Build for H3 SoC platform (default for ARM arch)])],
    [
        case $with_platform_h3 in
	    (y*)
	    	TARGET_PLATFORM_H3=true
		platform_specified=true
		platform_h3_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_H3=false
		platform_h3_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*)
	        TARGET_PLATFORM_H3=unk
		;;
	    (*)
	    	TARGET_PLATFORM_H3=false
		platform_h3_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-chip,
    [AS_HELP_STRING(
        [--with-platform-chip],
	[Build for Chip platform (default for ARM arch)])],
    [
        case $with_platform_chip in
	    (y*)
	    	TARGET_PLATFORM_CHIP=true
		platform_specified=true
		platform_chip_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_CHIP=false
		platform_chip_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*)
	        TARGET_PLATFORM_CHIP=unk
		;;
	    (*)
	        TARGET_PLATFORM_CHIP=false
		platform_chip_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-raspberry,
    [AS_HELP_STRING(
        [--with-platform-raspberry],
	[Build for Raspberry platform (default for ARM arch)])],
    [
        case $with_platform_raspberry in
	    (y*)
	    	TARGET_PLATFORM_RASPBERRY=true
		platform_specified=true
		platform_raspberry_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_RASPBERRY=false
		platform_raspberry_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*)
	        TARGET_PLATFORM_RASPBERRY=unk
		;;
	    (*)
	    	TARGET_PLATFORM_RASPBERRY=false
		platform_raspberry_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_ARG_WITH(platform-zedboard,
    [AS_HELP_STRING(
        [--with-platform-zedboard],
	[Build for Zedboard platform])],
    [
        case $with_platform_zedboard in
	    (y*)
	    	TARGET_PLATFORM_ZEDBOARD=true
		platform_specified=true
		platform_zedboard_reason="$cmdl_enab_msg"
		;;
	    (*)
	    	TARGET_PLATFORM_ZEDBOARD=false
		platform_zedboard_reason="$cmdl_disab_msg"
		;;
	esac
    ],
    [
        case $host_cpu in
	    (arm*)
	        TARGET_PLATFORM_ZEDBOARD=unk
		;;
	    (*)
	    	TARGET_PLATFORM_ZEDBOARD=false
		platform_zedboard_reason="$arch_disab_msg"
		;;
	esac
    ])

AC_SUBST(ARCH_CFLAGS)

if $platform_specified; then
    # Platform was explicitly specified using --with-platform-*;
    # disable anything not explicitly specified
    if test $TARGET_PLATFORM_PC = unk; then
	TARGET_PLATFORM_PC=false
	platform_pc_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_SOCFPGA = unk; then
	TARGET_PLATFORM_SOCFPGA=false
	platform_socfpga_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_BEAGLEBONE = unk; then
	TARGET_PLATFORM_BEAGLEBONE=false
	platform_beaglebone_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_H3 = unk; then
	TARGET_PLATFORM_H3=false
	platform_h3_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_CHIP = unk; then
	TARGET_PLATFORM_CHIP=false
	platform_chip_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_RASPBERRY = unk; then
	TARGET_PLATFORM_RASPBERRY=false
	platform_raspberry_reason="$cmdl_notspec_msg"
    fi
    if test $TARGET_PLATFORM_ZEDBOARD = unk; then
	TARGET_PLATFORM_ZEDBOARD=false
	platform_zedboard_reason="$cmdl_notspec_msg"
    fi
else
    # Platform was not explicitly specified; enable anything
    # applicable to this architecture and not explicitly disabled
    # (these tests performed earlier)
    if test $TARGET_PLATFORM_PC = unk; then
        TARGET_PLATFORM_PC=true
	platform_pc_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_SOCFPGA = unk; then
        TARGET_PLATFORM_SOCFPGA=true
	platform_socfpga_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_BEAGLEBONE = unk; then
        TARGET_PLATFORM_BEAGLEBONE=true
	platform_beaglebone_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_H3 = unk; then
        TARGET_PLATFORM_H3=true
	platform_h3_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_CHIP = unk; then
        TARGET_PLATFORM_CHIP=true
	platform_chip_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_RASPBERRY = unk; then
        TARGET_PLATFORM_RASPBERRY=true
	platform_raspberry_reason="$arch_enab_msg"
    fi
    if test $TARGET_PLATFORM_ZEDBOARD = unk; then
        TARGET_PLATFORM_ZEDBOARD=true
	platform_zedboard_reason="$arch_enab_msg"
    fi
fi


# Print messages about what platforms are to be enabled or disabled
AC_MSG_CHECKING(platform-pc)
AC_MSG_RESULT([$platform_pc_reason])

AC_MSG_CHECKING(platform-beaglebone)
AC_MSG_RESULT([$platform_beaglebone_reason])

AC_MSG_CHECKING(platform-h3)
AC_MSG_RESULT([$platform_h3_reason])

AC_MSG_CHECKING(platform-chip)
AC_MSG_RESULT([$platform_chip_reason])

AC_MSG_CHECKING(platform-socfpga)
AC_MSG_RESULT([$platform_socfpga_reason])

AC_MSG_CHECKING(platform-raspberry)
AC_MSG_RESULT([$platform_raspberry_reason])

AC_MSG_CHECKING(platform-zedboard)
AC_MSG_RESULT([$platform_zedboard_reason])

# every Machinekit instance needs a unique ID, so generate here.
# Can be changed later in etc/machinekit/machinekit.ini
AC_PATH_PROG(UUIDGEN, uuidgen)
if test "x$UUIDGEN" = "x"; then
  AC_MSG_ERROR([ uuidgen not found - please install package uuid-runtime ])
  AC_MSG_RESULT(no)
else
  MKUUID=`uuidgen`
  AC_MSG_RESULT(setting unique Machinekit UUID to $MKUUID)
  AC_SUBST([MKUUID])
fi

AC_MSG_CHECKING(whether to enable remote operation)
AC_ARG_ENABLE(remote,
    [  --enable-remote      enable remote zeroMQ services],
    [
	REMOTE=1
        AC_MSG_RESULT([configuring enable remote zeroMQ services])
    ],
    [
      AC_MSG_RESULT([local operation on IPC sockets only, zeroconf not used])
      REMOTE=0
    ])
AC_SUBST([REMOTE])

# this should move to /var/run eventually
# it might mean a subdirectory needs to be created with proper permissions
AC_MSG_CHECKING(which directory to use for IPC sockets and other transient files)
AC_ARG_WITH(rundir,
    [  --with-rundir=<directory>  directory for IPC sockets and other transient files (default /tmp)],
    [
	RUNDIR="$withval"
        AC_MSG_RESULT([configuring to use $RUNDIR for transient files like IPC sockets])
    ],
    [
      RUNDIR=/tmp
      AC_MSG_RESULT([using /tmp for IPC sockets and other transient files])
    ])
AC_DEFINE_UNQUOTED([RUNDIR], "$RUNDIR", [directory for IPC sockets and other transient files])

AC_SUBST([RUNDIR])

AC_MSG_CHECKING(whether to build programming examples)
AC_ARG_ENABLE(examples,
    [  --enable-examples      build included programming examples],
    [
	BUILD_EXAMPLES=yes
        AC_MSG_RESULT([configuring to build example programs])
    ],
    [
      AC_MSG_RESULT([not building example programs])
      BUILD_EXAMPLES=no
    ])

# protobuf-to-Javascript generator from  https://github.com/dcodeIO/ProtoBuf.js/wiki
AC_PATH_PROG(PROTO2JS,proto2js, none)
AC_SUBST([PROTO2JS])

AC_MSG_CHECKING(whether to build protobuf Javascript bindings)
AC_ARG_ENABLE(proto-js,
    [  --enable-proto-js    build Javascript bindings based on https://github.com/dcodeIO/ProtoBuf.js/wiki],
    [
	if test "$PROTO2JS" = "none"; then
	   AC_MSG_ERROR([Please install proto2js before building Javascript bindings.])
	fi
	BUILD_PROTO_JS=yes
        AC_MSG_RESULT([configuring to to build protobuf Javascript bindings])
    ],
    [
      AC_MSG_RESULT([not protobuf Javascript bindings])
      BUILD_PROTO_JS=no
    ])


AC_MSG_CHECKING(whether to use inb/outb or ppdev ioctl on the x86 for parport I/O)
AC_ARG_ENABLE(portable-parport,
    [  --enable-portable-parport      Build hal_parport using the ppdev ioctl instead of inb/outb],
    [
        case "$enableval" in
            Y*|y*)
		USE_PORTABLE_PARPORT_IO=yes
                AC_MSG_RESULT([explicitly configuring for ppdev ioctl])
            ;;
            N*|n*)
		USE_PORTABLE_PARPORT_IO=no
                AC_MSG_RESULT([explicitly disabling ppdev ioctl and using inb/outb])
            ;;
        esac
	if test -z "$USE_PORTABLE_PARPORT_IO"; then
	   AC_MSG_ERROR([ I dont understand $enableval, just yes or no ])
	fi
    ],
    [
      USE_PORTABLE_PARPORT_IO=no
      AC_MSG_RESULT([using defaults: $USE_PORTABLE_PARPORT_IO])
    ])

AC_MSG_CHECKING(whether to build unstable development code)
AC_ARG_ENABLE(dev,
    [  --enable-dev       build unstable development code],
    [
	BUILD_DEV=yes
        AC_MSG_RESULT([configuring to build unstable development code])
    ],
    [
      AC_MSG_RESULT([not building  development code])
      BUILD_DEV=no
    ])

##############################################################################
# Subsection 2.3.1                                                           #
# CK, protobuf, zmq, websockets, json, uriparse, avahi-client packages       #
##############################################################################

# FIXME concurrencykit breaks aarch64 tests on Focal, Bionic and
# Buster (but not Stretch!)
# https://github.com/machinekit/machinekit-hal/issues/317
AS_IF(
    [test $host_cpu != aarch64],
    [
	PKG_CHECK_MODULES(
	    [CK],
	    [ck >= 0.4.6],
	    [AC_DEFINE(HAVE_CK, [], [Use concurrencykit])],
	    [true],  dnl libck is optional
	)
    ]
)

PKG_CHECK_MODULES([ZMQ], [libzmq],
    [
        AC_DEFINE(HAVE_ZMQ, [], [zeroMQ library available])
	USE_ZMQ=yes
    ],)

PKG_CHECK_MODULES([CZMQ], [libczmq > 4.0],
    [
        AC_DEFINE(HAVE_CZMQ, [], [zeroMQ czmq library available])
	USE_CZMQ=yes
    ],)

PKG_CHECK_MODULES([PROTOBUF], [protobuf > 2.4.0],
    [
        AC_DEFINE(HAVE_PROTOBUF, [], [protobuf library available])
	USE_PROTOBUF=yes
    ],)

AC_PATH_PROG(PROTOC, protoc, "none")
if test $PROTOC = "none"
then
    AC_MSG_ERROR([protoc not found - protobuf-compiler package not installed?])
fi

AX_PYTHON_MODULE(google.protobuf.descriptor, 1)
AX_PYTHON_MODULE(google.protobuf.descriptor_pb2, 1)
AX_PYTHON_MODULE(google.protobuf.compiler.plugin_pb2, 1)

PKG_CHECK_MODULES([JANSSON], [jansson > 2.4],
    [
        AC_DEFINE(HAVE_JANSSON, [], [jansson JSON C bindings available])
	USE_JANSSON=yes
    ],)

PKG_CHECK_MODULES([URIPARSER], [liburiparser > 0.7.4],
   [
        AC_DEFINE(HAVE_URIPARSER, [], [uriparser library available])
	USE_URIPARSER=yes
   ],)

PKG_CHECK_MODULES([LWS], libwebsockets,
   [
        AC_DEFINE(HAVE_LWS, [], [libwebsockets library available])
	USE_LWS=yes
   ],)

AC_MSG_CHECKING(whether to build webtalk)
AC_ARG_ENABLE([webtalk],
    AS_HELP_STRING([--enable-webtalk="ARG"], [build Webtalk [ARG=yes] ]))

    AS_IF([test "x$enable_webtalk" = "xyes"], [
	if test "$USE_LWS" != "yes"; then
	    AC_MSG_ERROR([Please install libwebsockets before building Webtalk.])
	fi
	BUILD_WEBTALK=yes
        AC_MSG_RESULT([configuring to to build webtalk])
    ],
    [
      AC_MSG_RESULT([not building webtalk])
      BUILD_WEBTALK=no
    ])



PKG_CHECK_MODULES([SSL], libssl,
   [
        AC_DEFINE(HAVE_SSL, [], [libssl library available])
	USE_SSL=yes
   ],)


PKG_CHECK_MODULES([UUID], uuid,
   [
        AC_DEFINE(HAVE_UUID, [], [uuid library available])
	USE_UUID=yes
   ],)

PKG_CHECK_MODULES([AVAHI], [avahi-client > 0.6],
    [
        AC_DEFINE(HAVE_AVAHI, [], [avahi mDNS client library available])
	USE_AVAHI=yes
    ],)

PKG_CHECK_MODULES([LIBCGROUP], libcgroup,
   [
        AC_DEFINE(HAVE_LIBCGROUP, [], [libcgroup library available])
	USE_LIBCGROUP=yes
   ],)

##############################################################################
# Subsection 2.3.2                                                           #
# Dependencies for mkwrapper                                                 #
# pyftpdlib                                                                  #
##############################################################################

AX_PYTHON_MODULE(pyftpdlib.authorizers, 1)
AX_PYTHON_MODULE(pyftpdlib.handlers, 1)
AX_PYTHON_MODULE(pyftpdlib.servers, 1)


##############################################################################
# Subsection 2.5                                                             #
# Flavor configuration                                                       #
# - Check whether each flavor should be configured                           #
# - Sanity checks and configuration generation                               #
##############################################################################

AC_PRESERVE_HELP_ORDER()

AC_ARG_WITH(xenomai2,
    [AS_HELP_STRING([--with-xenomai2],
        [build Xenomai 2 userland threads])],
    [xenomai_from_cmdline=$withval
     test $withval = yes && all_flavors_default=no],
    [with_xenomai2=check])

if test "$with_xenomai2" != no; then
    # XENOMAI_THREADS_RTS:  look for the xeno-config executable
    XENOMAI_THREADS_RTS=''
    if test "$xeno_config_from_cmdline" = yes; then
        # user-supplied path
        XENOMAI_THREADS_RTS="$with_xeno_config"
    else
	# guess the path
	AC_PATH_PROGS([XENOMAI_THREADS_RTS],[xeno-config],0,$PATH:/usr/xenomai/bin)
    fi
    # check xeno-config path
    if test -n "$XENOMAI_THREADS_RTS"; then
        # path found, so check its validity: add '--skin=native' to
        # the variable; then --ldflags should return something
        # containing the string '-lnative'
	AC_MSG_CHECKING([usability of xenomai utility, $XENOMAI_THREADS_RTS])
	if test -x $XENOMAI_THREADS_RTS; then
	    # Check for Xenomai v.2 or v.3
        # This will need rework for real Xenomai 3 support
	    case $(xeno-config --version) in
	        2.*)
		    XENOMAI_SKIN=native
		    XENOMAI_V2=true
		    AC_MSG_RESULT(yes (v2))
		    ;;
		3.*)
		    #XENOMAI_SKIN=alchemy
		    XENOMAI_V2=false
		    with_xenomai_kernel=no  # No more xenomai kthreads in v3
		    #AC_MSG_RESULT(yes (v3))
            AC_MSG_RESULT(no)
		    ;;
	    esac
	    XENOMAI_THREADS_RTS="$XENOMAI_THREADS_RTS --skin=$XENOMAI_SKIN"
	else
	    XENOMAI_THREADS_RTS=''
	    AC_MSG_RESULT(no)
	fi
    fi
    # deal with nothing found in the right way
    if test -z "$XENOMAI_THREADS_RTS"; then
	if test "$xeno_config_from_cmdline" = yes; then
	    # --with-xeno-config specified, but invalid path
	    AC_MSG_ERROR(--with-xeno-config:  "$with_xeno_config":  bad path)
        elif test "$with_xenomai_kernel" = yes -o "$with_xenomai2" = yes; then
	    # --with-xenomai2{,-kernel} specified but can't find xeno-config
            AC_MSG_ERROR("xeno-config" not found; use --with-xeno-config")
	else
	    with_xenomai_kernel=no
	    with_xenomai2=no
	fi
    fi
fi

if test -n "$XENOMAI_THREADS_RTS"; then
    # XENOMAI_RTFLAGS:  test runtime library & get flags
    LIBS_hold="$LIBS"
    CFLAGS_hold="$CFLAGS"
    CPPFLAGS_hold="$CPPFLAGS"
    LIBS="$LIBS $($XENOMAI_THREADS_RTS --ldflags)"
    AC_PRUNE_DEFAULT_LDFLAGS(LIBS)
    CFLAGS="$CFLAGS $($XENOMAI_THREADS_RTS --cflags)"
    CPPFLAGS="$CPPFLAGS $($XENOMAI_THREADS_RTS --cflags)"
    AC_CHECK_LIB($XENOMAI_SKIN, rt_task_create,,
        with_xenomai2=no; with_xenomai_kernel=no)
    AC_CHECK_HEADERS($XENOMAI_SKIN/task.h,,
        with_xenomai2=no; with_xenomai_kernel=no)
    LIBS="$LIBS_hold"
    CFLAGS="$CFLAGS_hold"
    CPPFLAGS="$CPPFLAGS_hold"
fi

if test "$with_xenomai2" != no; then
    flags="$($XENOMAI_THREADS_RTS --cflags)"
    # Xenomai docs recommend turning off CONFIG_CC_STACKPROTECTOR
    # on all arches but x86_64; this causes missing symbols without
    # this CFLAG
    if test "$host_cpu" != x86_64; then
        flags="$flags -fno-stack-protector"
    fi
    XENOMAI_RTFLAGS="$flags"
    # xenomai kernel math options
    flags="-ffast-math -mhard-float"
    if test "$($XENOMAI_THREADS_RTS --arch)" = x86; then
        flags="$flags -msse -funsafe-math-optimizations"
        # When using SSE instructions, not normally allowed in the
        # kernel, the stack must be aligned at 16 bytes.  Later
        # kernels (3.8.13, but not 3.5.7) try to set
        # -mpreferred-stack-boundary=3 on x86_64 arch, so force it.
	flags="$flags -mpreferred-stack-boundary=4"
    fi
    # ldflags
    flags="$($XENOMAI_THREADS_RTS --ldflags)"
    AC_PRUNE_DEFAULT_LDFLAGS(flags)
    XENOMAI_LDFLAGS+="$XENOMAI_THREADS_LDFLAGS $flags"
fi

AC_MSG_CHECKING(whether to build Xenomai 2 userland threads)
test "$with_xenomai2" = check && with_xenomai2=yes
test -z "$XENOMAI_THREADS_RTS" && with_xenomai2=no
if test $with_xenomai2 = no -a "$xenomai_from_cmdline" = yes; then
    AC_MSG_ERROR([Requested '--with-xenomai2', but unable to configure])
fi
AC_MSG_RESULT($with_xenomai2)


##############################################################################
# Subsection 2.6                                                             #
# Hardware driver detection                                                  #
# - Configure libudev                                                        #
##############################################################################

AC_MSG_CHECKING(whether to build hardware drivers)
AC_ARG_ENABLE(drivers,
    [AS_HELP_STRING([--enable-drivers],[Build hardware drivers])],
    [with_drivers=$enableval],
    [with_drivers=check])
if test "$with_drivers" = check; then
    with_drivers=yes
fi
AC_MSG_RESULT($with_drivers)


# test usability of libudev, needed by drivers
PKG_CHECK_MODULES(LIBUDEV, libudev, with_libudev=yes, with_libudev=no)


##############################################################################
# Subsection 2.7                                                             #
# Pass configuration out of script                                           #
# - Substitution variables (Makefile.inc.in, realtime.in, etc.               #
# - config.h macro definitions                                               #
##############################################################################

if test "$with_drivers" = yes; then
   AC_DEFINE(BUILD_DRIVERS, [], [build hardware drivers])
fi
AC_SUBST(BUILD_DRIVERS,[$with_drivers])

AC_SUBST(BUILD_EXAMPLES)
if test "$BUILD_EXAMPLES" = yes; then
   AC_DEFINE(BUILD_EXAMPLES, [], [build programming examples])
fi

AC_SUBST(PROTOC)

AC_SUBST(BUILD_DEV)
AC_SUBST(BUILD_PROTO_JS)
AC_SUBST(BUILD_WEBTALK)

AC_SUBST([ZMQ_CFLAGS])
AC_SUBST([ZMQ_LIBS])

AC_SUBST([CZMQ_CFLAGS])
AC_SUBST([CZMQ_LIBS])

AC_SUBST([PROTOBUF_CFLAGS])
AC_SUBST([PROTOBUF_LIBS])

AC_SUBST([AVAHI_CFLAGS])
AC_SUBST([AVAHI_LIBS])

AC_SUBST([JANSSON_CFLAGS])
AC_SUBST([JANSSON_LIBS])

AC_SUBST([URIPARSER_CFLAGS])
AC_SUBST([URIPARSER_LIBS])

AC_SUBST([LWS_CFLAGS])
AC_SUBST([LWS_LIBS])

AC_SUBST([SSL_CFLAGS])
AC_SUBST([SSL_LIBS])

AC_SUBST([UUID_CFLAGS])
AC_SUBST([UUID_LIBS])

AC_SUBST([LIBCGROUP_CFLAGS])
AC_SUBST([LIBCGROUP_LIBS])

AC_SUBST([USE_ZMQ])
AC_SUBST([USE_CZMQ])
AC_SUBST([USE_PROTOBUF])
AC_SUBST([USE_JANSSON])
AC_SUBST([USE_LWS])
AC_SUBST([USE_URIPARSER])
AC_SUBST([USE_AVAHI])
AC_SUBST([USE_SSL])
AC_SUBST([USE_UUID])
AC_SUBST([USE_LIBCGROUP])

AC_SUBST(LIBUDEV_CFLAGS)
AC_SUBST(LIBUDEV_LIBS)
AC_DEFINE(HAVE_LIBUDEV, [], [libudev installed and available])

if test "$USE_PORTABLE_PARPORT_IO" = yes; then
   AC_DEFINE(USE_PORTABLE_PARPORT_IO, [], [use ppdev ioctl instead of inb/outb])
fi
AC_SUBST(USE_PORTABLE_PARPORT_IO)

# Platform
if $TARGET_PLATFORM_PC; then
   AC_DEFINE(TARGET_PLATFORM_PC, [], [build for PC platform])
   target_platform_pc_val=yes
fi
AC_SUBST(TARGET_PLATFORM_PC,$target_platform_pc_val)

if $TARGET_PLATFORM_SOCFPGA; then
   AC_DEFINE(TARGET_PLATFORM_SOCFPGA, [], [build for Socfpga platform])
   target_platform_socfpga_val=yes
fi
AC_SUBST(TARGET_PLATFORM_SOCFPGA,$target_platform_socfpga_val)

if $TARGET_PLATFORM_BEAGLEBONE; then
   AC_DEFINE(TARGET_PLATFORM_BEAGLEBONE, [], [build for BeagleBone platform])
   target_platform_beaglebone_val=yes
fi
AC_SUBST(TARGET_PLATFORM_BEAGLEBONE,$target_platform_beaglebone_val)

if $TARGET_PLATFORM_H3; then
   AC_DEFINE(TARGET_PLATFORM_H3, [], [build for H3 SoC platform])
   target_platform_h3_val=yes
fi
AC_SUBST(TARGET_PLATFORM_H3,$target_platform_h3_val)

if $TARGET_PLATFORM_CHIP; then
   AC_DEFINE(TARGET_PLATFORM_CHIP, [], [build for Chip platform])
   target_platform_chip_val=yes
fi
AC_SUBST(TARGET_PLATFORM_CHIP,$target_platform_chip_val)

if $TARGET_PLATFORM_RASPBERRY; then
   AC_DEFINE(TARGET_PLATFORM_RASPBERRY, [], [build for Raspberry Pi platform])
   target_platform_raspberry_val=yes
fi
AC_SUBST(TARGET_PLATFORM_RASPBERRY,$target_platform_raspberry_val)

if $TARGET_PLATFORM_ZEDBOARD; then
   AC_DEFINE(TARGET_PLATFORM_ZEDBOARD, [], [build for Zedboard platform])
   target_platform_zedboard_val=yes
fi
AC_SUBST(TARGET_PLATFORM_ZEDBOARD,$target_platform_zedboard_val)

############################################################
# thread-specific -DDEFINE and Makefile.inc variables

# Xenomai general settings
if test "$XENOMAI_V2" = true; then
    AC_DEFINE([XENOMAI_V2],[],[Xenomai v.2])
fi
AC_DEFINE_UNQUOTED([XENOMAI_SKIN],$XENOMAI_SKIN,
	[Xenomai skin ('native' for v2)])
    #[Xenomai skin ('native' for v2, 'alchemy' for v3)])

# Xenomai userland settings
if test "$with_xenomai2" = yes; then
    AC_DEFINE([HAVE_XENOMAI2_THREADS],[],[Build Xenomai 2 userland threads])
fi
AC_SUBST([HAVE_XENOMAI2_THREADS],[$with_xenomai2])
AC_SUBST([XENOMAI_THREADS_RTS])
AC_SUBST([XENOMAI_RTFLAGS])
AC_SUBST([XENOMAI_LDFLAGS])

# while we are at it, drop a git scent mark
GIT_VERSION=unknown
GIT_CONFIG_SHA=`../scripts/get-git-sha`

gitcmd=`which git`
if test -n "$gitcmd"; then
   version=`(cd ..;scripts/get-version-from-git)` 2>/dev/null
   if test -n "$version"; then
      GIT_VERSION=$version
   fi
else
   GIT_VERSION='git not installed at configure time'
fi

AC_SUBST(GIT_VERSION)
AC_SUBST(GIT_CONFIG_SHA)


HAL_HOME=`(cd .. ; pwd)`
AC_SUBST([HAL_HOME])


##############################################################################
# Section 3                                                                  #
# additional checking, ensure gcc > 4.4                                      #
# Subsection 3.1 - checking for a CC (we must use the same one used for RT)  #
# Subsection 3.2 - define default dirs                                       #
# Subsection 3.3 - check for GTK                                             #
# Subsection 3.4 - check for utility programs needed to build and run EMC    #
# Subsection 3.5 - check for programs needed to build documentation          #
##############################################################################

### ensure suficient adherence to C11 standard to allow forward declaration
### of typedefs etc - >= gcc-4.6

GCC_VERSION=$(gcc -dumpversion)
MAJ_VERSION=4
MIN_VERSION=6
MAJOR_VERSION=${GCC_VERSION:0:1}
MINOR_VERSION=${GCC_VERSION:2:1}

if (($MAJOR_VERSION == $MAJ_VERSION))
then
    if (($MINOR_VERSION < $MIN_VERSION))
    then
        AC_MSG_ERROR([gcc version = $GCC_VERSION, requires 4.6 or higher])
    fi
fi


##############################################################################
# Subsection 3.1 - checking for a CC (we must use the same one used for RT)  #
# Check CC version - (P.C.) We need to verify the compiler is the same one   #
# used for the realtime extensions... Hence the need to find the RT signature#
# first.                                                                     #
# $RTS --cc should return the C compiler used - Verify this is acceptable.   #
# if version is gcc-2.96 check for alternative                               #
##############################################################################

AC_MSG_CHECKING([for usability of rdtscll from asm/msr.h])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <asm/msr.h>
#include <stdio.h>
void use_rdtscll(void) { long long tsc; rdtscll(tsc); }
]], [[]])],[
        MSR_H_USABLE=yes
        AC_DEFINE([MSR_H_USABLE], [], [Define to 1 if asm/msr.h is usable and defines rdtscll])
    ],[MSR_H_USABLE=no])
AC_MSG_RESULT($MSR_H_USABLE)

AC_MSG_CHECKING([for usability of linux/hidraw.h])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/ioctl.h>
#include <linux/hidraw.h>
long hidiocgrawinfo = HIDIOCGRAWINFO;
    ]], [[]])],[
	HIDRAW_H_USABLE=yes
        AC_DEFINE([HIDRAW_H_USABLE], [], [Define to 1 if linux/hidraw.h is usable and defines HIDIOCGRAWINFO])
],[HIDRAW_H_USABLE=no])
AC_MSG_RESULT($HIDRAW_H_USABLE)
AC_SUBST([HIDRAW_H_USABLE])


#
# check for libmodbus3
#

AC_ARG_WITH(
    [libmodbus],
    [  --with-libmodbus                        Specify whether or not to build
                                          the drivers that use libmodbus
                                          (defaults to "yes")],
    [WITH_LIBMODBUS=$withval],
    [WITH_LIBMODBUS=check]
)

AS_IF(
    [test $WITH_LIBMODBUS = yes -o $WITH_LIBMODBUS = check ],
    [
	PKG_CHECK_MODULES(
	    LIBMODBUS,
	    libmodbus >= 3,
	    [ AC_SUBST(HAVE_LIBMODBUS3, yes) ],
	    [ AC_MSG_ERROR([libmodbus3 requested but not found]) ])
    ]
)


#
# check for libusb-1.0
#

AC_ARG_WITH(
    [libusb-1.0],
    [  --with-libusb-1.0                       Specify whether or not to build
                                          the drivers that use libusb-1.0
                                          (defaults to "yes")],
    [WITH_LIBUSB10=$withval],
    [WITH_LIBUSB10=yes]
)

AS_IF(
    [test "x$WITH_LIBUSB10" = "xyes"],
    [
	PKG_CHECK_MODULES(
	    LIBUSB10,
	    libusb-1.0,
	    [ AC_SUBST(HAVE_LIBUSB10, yes) ],
	    [ AC_MSG_ERROR([not found]) ])
    ]
)

#
# check for LTTNG
# the lttng-ust package should be enough for now
#
AC_ARG_WITH(
    [lttng],
    [  --with-lttng                       Specify whether or not to use
                                          the LTTNG tracing framework
                                          (defaults to "no")],
    [WITH_LTTNG=$withval],
    [WITH_LTTNG=no]
)

AS_IF(
    [test "x$WITH_LTTNG" = "xyes"],
    [
	PKG_CHECK_MODULES(LTTNG_UST, lttng-ust,
	    [
	      HAVE_LTTNG_UST=yes
	      AC_DEFINE([HAVE_LTTNG_UST], [], [if lttng-ust support is available])
	    ],
	    [ AC_MSG_ERROR([package lttng-ust not found]) ]
	    )
    ]
)
AC_SUBST(HAVE_LTTNG_UST)

##############################################################################
# Subsection 3.2 - define default dirs, these get used in a lot of places    #
# we decide based on RIP or install where stuff goes                         #
##############################################################################

if test "$RUN_IN_PLACE" = "yes"; then
    prefix=${BUILD_TOPLEVEL}
    HAL_INCLUDE_DIR=${BUILD_TOPLEVEL}/include
    HAL_LIB_DIR=${BUILD_TOPLEVEL}/lib
    HAL_LDFLAGS=-L${HAL_LIB_DIR}
else
    RUN_IN_PLACE=no
    HAL_HOME=$prefix
    HAL_INCLUDE_DIR=${prefix}/include/machinekit
    HAL_LIB_DIR=
    HAL_LDFLAGS=
fi

###################################

AC_SUBST([RUN_IN_PLACE])
AC_SUBST([HAL_INCLUDE_DIR])
AC_SUBST([HAL_LIB_DIR])
AC_SUBST([HAL_LDFLAGS])

fe () {
    # Fully expand argument.  Example:
    # ${datadir} -> ${datarootdir} -> ${prefix}/share -> /usr/local
    case "$1" in
    *\$*) eval fe \""$1"\" ;;
    *) echo "$1" ;;
    esac
}

HAL_SYSTEM_CONFIG_DIR=${sysconfdir}/machinekit

if test "xyes" = "x$RUN_IN_PLACE"; then
    HAL_LATENCY_SCRIPT=$HAL_HOME/scripts/latency-test
    HAL_SUFFIX=" (run-in-place)"
    HAL_ICON=$HAL_HOME/machinekiticon.png
    HAL_BIN_DIR=$HAL_HOME/bin
    HAL_LIBEXEC_DIR=$HAL_HOME/libexec
    HAL_LANG_DIR=$HAL_HOME/src/objects
    HAL_PO_DIR=$HAL_HOME/share/locale
    HAL_HELP_DIR=$HAL_HOME/help
    HAL_RTLIB_DIR=$HAL_HOME/rtlib
    HAL_MODULES_DIR=$HAL_RTLIB_DIR/modules
    REALTIME=$HAL_HOME/scripts/realtime
    HAL_IMAGE_DIR=$HAL_HOME
else
    HAL_HOME=${prefix}
    HAL_BIN_DIR=${prefix}/bin
    HAL_LIBEXEC_DIR=${libexecdir}/machinekit
    HAL_LATENCY_SCRIPT=$HAL_BIN_DIR/latency-test
    HAL_SCRIPT=$HAL_BIN_DIR/emc
    HAL_SUFFIX=""
    HAL_ICON=machinekiticon
    HAL_PO_DIR=${prefix}/share/locale
    HAL_HELP_DIR=${prefix}/share/doc/machinekit
    HAL_RTLIB_DIR=${prefix}/lib/machinekit
    HAL_MODULES_DIR=$HAL_RTLIB_DIR/modules
    REALTIME=${bindir}/realtime
    HAL_IMAGE_DIR=$(fe "$datadir")/machinekit
fi

# Paths in config.h should be reduced to one:  HAL_SYSTEM_CONFIG_DIR.
# This should contain the .ini file that points to everything else.

# do this here since substituted into files
# needed below after substitution
MACHINEKIT_INI="$HAL_SYSTEM_CONFIG_DIR/machinekit.ini"
AC_SUBST([MACHINEKIT_INI])

AC_DEFINE_UNQUOTED([HAL_HOME], "$HAL_HOME", [Prefix or RIP directory])
AC_DEFINE_UNQUOTED([MACHINEKIT_INI], "$MACHINEKIT_INI", [path of global machinekit.ini file])
AC_DEFINE_UNQUOTED([HAL_BIN_DIR], "$HAL_BIN_DIR", [Directory for binaries])
AC_DEFINE_UNQUOTED([HAL_RTLIB_DIR], "$HAL_RTLIB_DIR", [Directory for ulapi shared objects])
AC_DEFINE_UNQUOTED([HAL_MODULES_DIR], "$HAL_MODULES_DIR",
                                       [Directory for rtapi shared objects])
AC_DEFINE_UNQUOTED([HAL_PO_DIR], "$HAL_PO_DIR", [Directory for po/mo translation files])
AC_DEFINE_UNQUOTED([HAL_IMAGE_DIR], "$HAL_IMAGE_DIR", [Directory for images])
AC_DEFINE_UNQUOTED([GIT_VERSION], "$GIT_VERSION", [Git version tag])
AC_DEFINE_UNQUOTED([GIT_CONFIG_SHA], "$GIT_CONFIG_SHA", [SHA valid when configure was run])

AC_SUBST([HAL_SYSTEM_CONFIG_DIR])
AC_SUBST([HAL_BIN_DIR])
AC_SUBST([HAL_LIBEXEC_DIR])
AC_SUBST([HAL_HELP_DIR])
AC_SUBST([HAL_RTLIB_DIR])
AC_SUBST([HAL_MODULES_DIR])
AC_SUBST([HAL_LANG_DIR])
AC_SUBST([REALTIME])
AC_SUBST([HAL_IMAGE_DIR])
AC_SUBST([HAL_SCRIPT])
AC_SUBST([HAL_LATENCY_SCRIPT])
AC_SUBST([HAL_LATENCYPLOT_SCRIPT])
AC_SUBST([HAL_SUFFIX])
AC_SUBST([HAL_ICON])


##############################################################################
# Subsection 3.3 - check for GTK                                             #
# FIXME: allow it to be enabled or disabled command line                     #
##############################################################################

PKG_CHECK_MODULES(GLIB, glib-2.0)

AC_ARG_ENABLE(gtk,
    [  --disable-gtk        Disable the parts of Machinekit that depend on GTK],
    [
	case "$enableval" in
	Y*|y*)
	    BUILD_GTK=yes ;;
	*)
	    BUILD_GTK=no ;;
	esac
    ],
    [BUILD_GTK=yes])

if test "$BUILD_GTK" = "yes"; then
    PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.4.0],
	[
    	    AC_DEFINE(HAVE_GTK, [1], [gtk > 2.4 available HAVE_GTK set])
	    HAVE_GTK=yes
	],
	[ AC_MSG_ERROR([no gtk+-2.0 found; use --disable-gtk])]
	[ AC_PRUNE_DEFAULT_LDFLAGS(GTK_LIBS) ] )
    PKG_CHECK_MODULES(GNOMEPRINT, libgnomeprintui-2.2,
        [
	    GTK_CFLAGS="$GTK_CFLAGS $GNOMEPRINT_CFLAGS"
	    GTK_LIBS="$GTK_LIBS $GNOMEPRINT_LIBS"
	    HAVE_GNOMEPRINT=yes
	], :)
fi

AC_SUBST(HAVE_GNOMEPRINT)
AC_SUBST(HAVE_GTK)
AC_SUBST(GTK_LIBS)
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GLIB_LIBS)
AC_SUBST(GLIB_CFLAGS)

##############################################################################
# Subsection 3.4 - check for utility programs needed to build and run EMC    #
#                                                                            #
# Check for all the utility programs we need to build and install emc        #
# as well as those we use in the emc scripts...                              #
##############################################################################

SPATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin

# make this optional - it will likely only result in warnings
AX_CXX_COMPILE_STDCXX_11(noext,optional)

AC_PROG_MAKE_SET
AC_PROG_RANLIB
AC_PATH_PROG(AR,ar)
AC_PATH_PROG(INSTALL, install)



AC_PATH_PROG(SED, sed, "none")
if test $SED = "none"
then
    AC_MSG_ERROR([sed not found])
fi

AC_PATH_PROG(PS, ps, "none")
if test $PS = "none"
then
    AC_MSG_ERROR([ps not found])
fi

AC_PATH_PROG(KILL, kill, "none")
if test $KILL = "none"
then
    AC_MSG_ERROR([kill not found])
fi

AC_PATH_PROG(WHOAMI, whoami, "none")
if test $WHOAMI = "none"
then
    AC_MSG_ERROR([whoami not found])
fi

AC_PATH_PROG(AWK, awk, "none")
if test $AWK = "none"
then
    AC_MSG_ERROR([awk not found])
fi

AC_PATH_PROG(PIDOF, pidof, "none", $SPATH)
if test $PIDOF = "none"
then
    AC_MSG_ERROR([pidof not found])
fi

AC_PATH_PROG(IPCS, ipcs, "none")
if test $IPCS = "none"
then
    AC_MSG_ERROR([ipcs not found])
fi

AC_PATH_PROG(FUSER, fuser, "none", $SPATH)
if test $FUSER = "none"
then
    AC_MSG_ERROR([fuser not found])
fi

AC_PATH_PROG(YAPPS2, yapps2, "none")
if test $YAPPS2 = "none"; then
    AC_PATH_PROG(YAPPS, yapps, "none")
    if test $YAPPS = "none"; then
        AC_MSG_ERROR([No yapps2 or yapps executable found])
    else
        YAPPS2=$YAPPS
    fi
fi

# MANDB empty is handled in doc/Submakefile
AC_PATH_PROG(MANDB, mandb, "")

##############################################################################
# Subsection 3.5 - check for programs needed to build documentation          #
#                                                                            #
# Check for programs we need to build and install docs.                      #
# (Optional, if not present, just don't build the docs.)                     #
##############################################################################

AC_MSG_CHECKING(whether pydot capability required)
AC_ARG_ENABLE(pydot,
    [  --enable-pydot      enable python-pydot graphing],
    [
    PYDOT=yes
    AX_PYTHON_MODULE(pydot, 1)

    AC_PATH_PROG(XDOT, xdot, "none")
    if test $XDOT = "none"
    then
        AC_MSG_ERROR([xdot not found - xdot package not installed?])
    fi

        AC_MSG_RESULT([checked for python-pydot and xdot])
    ],
    [
      AC_MSG_RESULT([not checking for python-pydot and xdot])
    ])

AC_MSG_CHECKING([whether to build documentation])
AC_ARG_ENABLE(build-documentation,
    [  --enable-build-documentation   Build asciidoc documentation.],
    [
        BUILD_DOCS=yes
        AC_MSG_RESULT([ASCIIDOC build requested])
    ],
    [
        BUILD_DOCS=no
        AC_MSG_RESULT([no])
    ])

AC_SUBST(BUILD_DOCS)
#AC_SUBST(BUILD_DOCS_PDF)
#AC_SUBST(BUILD_DOCS_HTML)

##############################################################################
# Section 4 - Important headers, functions and gloabl defines.               #
#                                                                            #
##############################################################################

# This section gets inserted in to config.h.in when autoheader is run.
# Global and common defines should be here rather than duplicated in
# multiple places. Keep screwball constructs out of this, and it can
# be used in both kernel space and user space.


AH_TOP([/********************************************************************
* Description: config.h
*
*	Common defines used in many hal source files.
*       To add to this file, edit Section 4 in configure.ac
*       and then run autoheader.
*
* Author: Autogenerated by autoheader
* License: LGPL Version 2
* System: Linux
*
* Copyright (c) 2004 All rights reserved.
********************************************************************/
#ifndef HAL_CONFIG_H
#define HAL_CONFIG_H

/* LINELEN is used throughout for buffer sizes, length of file name strings,
   etc. Let's just have one instead of a multitude of defines all the same. */
#define LINELEN 255

// format of zeroMQ IPC socket pathnames
// pass: RUNDIR, rtapi_instance, service name, uuid
// service name is: log, rtapi, halrcomp etc
#define ZMQIPC_FORMAT "ipc://%s/%d.%s.%s"

])

AH_VERBATIM([_GNU_SOURCE],
[/* Enable GNU extensions on systems that have them.  */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
])

AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_FUNCS(semtimedop)
LIBS_hold=$LIBS
LIBS="$LIBS -lrt"

AC_CHECK_FUNCS(clock_getres)


AC_MSG_CHECKING([for sincos function])
sincos_ok=yes
AC_LINK_IFELSE([AC_LANG_PROGRAM([[double a, b;]], [[sincos(1.0, &a, &b);]])],[AC_DEFINE(
        HAVE_SINCOS,
        1,
        Define to 1 if sincos is available.
    )],[sincos_ok=no
])
AC_MSG_RESULT([$sincos_ok])

AC_CHECK_FUNCS(__sincos)
LIBS=$LIBS_hold

AH_BOTTOM(#endif
)

##############################################################################
# Section 5 - Generate rtapi.ini.sh.in                                       #
#                                                                            #
# Add per-flavor sections to the rtapi.ini generator                         #
##############################################################################

AC_MSG_NOTICE([Building rtapi.ini generator script])
cp ../scripts/gen-rtapi.ini.sh.in.tmpl ../scripts/gen-rtapi.ini.sh.in

##############################################################################
# Section 7 - Miscelaneous support                                           #
#                                                                            #
# Subsection 7.1. - provides DATE to output it to the generated files        #
# Subsection 7.2. - user option to convince make to be quiet during make     #
##############################################################################

# provides DATE in order to output it to the generated files
DATE=$(date)
AC_SUBST([DATE])
AC_PATH_XTRA

# check for readline.h and friends, optional for halcmd
AC_CHECK_HEADERS(readline/readline.h, [HAVE_READLINE=yes], [HAVE_READLINE=no])
AC_CHECK_HEADERS(readline/history.h, [], [HAVE_READLINE=no])

echo "Trying readline without -ltermcap"
AC_CHECK_LIB(readline, readline, [HAVE_READLINE_NOTERMCAP=yes], [])
unset ac_cv_lib_readline_readline
echo "Trying readline with -ltermcap"
AC_CHECK_LIB(readline, readline, [HAVE_READLINE_TERMCAP=yes], [], -ltermcap)
unset ac_cv_lib_readline_readline

if test "x$HAVE_READLINE_NOTERMCAP" = "xyes"; then
    echo "Readline does not require -ltermcap"
    READLINE_LIBS="-lreadline"
elif test "x$HAVE_READLINE_TERMCAP" = "xyes"; then
    echo "Readline requires -ltermcap"
    READLINE_LIBS="-lreadline -ltermcap"
else
    HAVE_READLINE=no
fi

if test "x$HAVE_READLINE" = "xyes"; then
    AC_DEFINE([HAVE_READLINE], [], [Define to 1 if you have the 'readline' library (-lreadline) and required headers])
else
    AC_MSG_ERROR([Required library 'readline' missing.])
fi
AC_SUBST([HAVE_READLINE])
AC_SUBST([READLINE_LIBS])


# libbacktrace library:
# with gcc 4.8 and later, libbacktrace is bundled with libgcc-dev-<gcc-version>
# the includes are just "backtrace.h" etc and -lbacktrace is used for linking

# for earlier gcc versions, libbacktrace can be built from
# https://github.com/mhaberler/libbacktrace, in which case the includes are named
# libbacktrace/backtrace.h etc, typically installed in /usr/local

# bundled version
AC_CHECK_HEADERS(backtrace.h)
# custom installed version
AC_CHECK_HEADERS(libbacktrace/backtrace.h)

# the library proper - if found, use -lbacktrace which should work for
# bundled and /usr/local/lib installs:
LIBBACKTRACE=""
AC_CHECK_LIB(backtrace, backtrace_simple,
	[
	    AC_DEFINE(HAVE_LIBBACKTRACE, [], [libbacktrace available])
	    LIBBACKTRACE="-lbacktrace"
	],[])

AC_SUBST([LIBBACKTRACE])

##############################################################################
# Section 8 - Language support                                               #
#                                                                            #
# i18n Language support:                                                     #
# see http://cvs.gnome.org/viewcvs/intltool/doc/I18N-HOWTO?rev=1.3           #
##############################################################################

# if you don't have nls tools, allow a way out!

AC_ARG_ENABLE(nls,
              [  --disable-nls           don't use NLS],
              USE_NLS=no, USE_NLS=yes)
AC_SUBST(USE_NLS)

if test "$USE_NLS" = "yes"; then
  AC_CHECK_HEADERS(locale.h)
  AC_CHECK_FUNCS(setlocale)
  AC_SUBST(HAVE_LOCALE_H)

# Add languages here when they are translated.
# Grep the LINGUAS file.
  LANGUAGES=""
  AC_SUBST(LANGUAGES)
  AC_CHECK_HEADERS(libintl.h)
  AC_CHECK_LIB(intl,gettext)
  AC_SUBST(HAVE_LIBINTL_H)
  AC_SUBST(HAVE_LIBINTL)

# The default locale directory is /usr/share/locale - This is generally fixed
# by the distribution....
  dnl Handle localedir
  LOCALEDIR='/usr/share/locale'
  AC_ARG_WITH(locale-dir,
  [  --with-locale-dir=DIR   Location of the locale file(s)
                          [DATADIR/locale]],[
    if test x$withval = xyes; then
      AC_MSG_WARN(Usage is: --with-locale-dir=basedir)
    else
      if test x$withval = xno; then
        AC_MSG_WARN(Usage is: --with-locale-dir=basedir)
      else
        LOCALEDIR=$withval
      fi
    fi
  ])
  AC_SUBST(LOCALEDIR)
fi

AC_PATH_PROG(XGETTEXT,xgettext,none)
AC_PATH_PROG(MSGFMT,msgfmt,none)
if test "$MSGFMT" = none -o "$XGETTEXT" = none; then
   AC_MSG_ERROR(install gettext)
fi
AC_SUBST(XGETTEXT)
AC_SUBST(MSGFMT)

AC_MSG_CHECKING(for Python support)
AC_ARG_ENABLE(python,
    [  --disable-python        Disable the parts of Machinekit that depend on Python],
    [
	case "$enableval" in
	Y*|y*)
	    BUILD_PYTHON=yes ;;
	*)
	    BUILD_PYTHON=no ;;
	esac
    ],
    [BUILD_PYTHON=yes])

AC_MSG_RESULT($BUILD_PYTHON)

if test "$BUILD_PYTHON" = "yes"; then
    if test "$PYTHON" = "none"; then
	AC_MSG_ERROR([Python missing.  Install it or specify --disable-python to skip the parts of Machinekit that depend on Python])
    fi

    AX_PYTHON_DEVEL(>= '3.2')
    AC_PRUNE_DEFAULT_LDFLAGS(PYTHON_LIBS)

    # Get the CFLAGS and LIBS for Boost
    AX_BOOST_BASE(1.34, , [AC_MSG_ERROR([Boost 1.34.0 or newer required])])

    AC_MSG_CHECKING(for site-package location)
    SITEPY=`$PYTHON -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(1))'`
    AC_MSG_RESULT($SITEPY)

fi

AC_SUBST([BUILD_PYTHON])
AC_SUBST([SITEPY])


##############################################################################
# files that get created by ./configure                                      #
##############################################################################
AC_CONFIG_HEADER(rtapi/rtapi.h)
AC_CONFIG_FILES([../scripts/gen-rtapi.ini.sh])
AC_CONFIG_FILES([../scripts/halrun], [chmod +x ../scripts/halrun])
AC_CONFIG_FILES([../scripts/rip-environment], [chmod +x ../scripts/rip-environment])
AC_CONFIG_FILES([../scripts/realtime], [chmod +x ../scripts/realtime])
AC_CONFIG_FILES(Makefile.inc)
AC_CONFIG_FILES(Makefile.modinc)
AC_CONFIG_FILES(../share/pkgconfig/machinekit-hal.pc)
AC_CONFIG_FILES(machinekitcfg.py-tmp)
AC_CONFIG_FILES(../scripts/machinekit.ini.tmpl)
AC_OUTPUT

# if there is no machinekit.ini file, use the autogenerated one;
# else just ensure the MKUUID is unique but dont touch other options
# as the user might have adapted it already


if test "$RUN_IN_PLACE" = "yes"; then
    AC_MSG_CHECKING(if $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini exists with valid MKUUID )
    if test -e "$BUILD_TOPLEVEL/etc/machinekit/machinekit.ini"; then
	../scripts/fix-uuid $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini $MKUUID ;
	AC_MSG_RESULT($BUILD_TOPLEVEL/etc/machinekit/machinekit.ini file exists, ensured MKUUID was unique)
    else
	AC_MSG_RESULT($BUILD_TOPLEVEL/etc/machinekit/machinekit.ini does not exist - creating one)
	mkdir -p  $BUILD_TOPLEVEL/etc/machinekit
	cp ../scripts/machinekit.ini.tmpl $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini
	../scripts/fix-uuid $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini $MKUUID ;
	AC_MSG_RESULT(please review and edit options in $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini as needed!)
    fi
else
    ## if packaging we don't want to give MKUUID a unique uuid yet - else all packages will have same one
    mkdir -p  $BUILD_TOPLEVEL/etc/machinekit
    cp ../scripts/machinekit.ini.tmpl $BUILD_TOPLEVEL/etc/machinekit/machinekit.ini
fi


# clean up machinekitcfg.py:
# subsitute "yes" by True
# subsitute "no" by False
AC_MSG_RESULT(touching up $BUILD_TOPLEVEL/lib/python/machinekit/config.py)
mkdir -p $BUILD_TOPLEVEL/lib/python/machinekit
sed -e 's/"yes"/True/g' -e 's/"no"/False/g' \
    <machinekitcfg.py-tmp \
    >machinekitcfg.py-tmp2
# recursively subsitute variables
while : ; do
    sed -e 's/\"/\\"/g' \
        <machinekitcfg.py-tmp2 \
        >machinekitcfg.py-tmp3
    echo -e "$(eval "echo -e \"`<machinekitcfg.py-tmp3`\"")" \
        >machinekitcfg.py-tmp4
    cmp --silent machinekitcfg.py-tmp2 machinekitcfg.py-tmp4
    RESULT=$?
    rm machinekitcfg.py-tmp2 machinekitcfg.py-tmp3
    mv machinekitcfg.py-tmp4 machinekitcfg.py-tmp2
    [[ $RESULT -ne 0 ]] || break
done
cat machinekitcfg.py-tmp2 > $BUILD_TOPLEVEL/lib/python/machinekit/config.py
rm machinekitcfg.py-tmp2
AC_MSG_CHECKING(usability of $BUILD_TOPLEVEL/lib/python/machinekit/config.py)
$PYTHON $BUILD_TOPLEVEL/lib/python/machinekit/config.py
AC_MSG_RESULT(done)

##############################################################################
# message to the user what to do next, after a succesfull ./configure        #
##############################################################################
bold () {
    if tty > /dev/null 2>&1 && type -path tput > /dev/null 2>&1;
    then
        tput smso
    fi
}

offbold () {
    if tty > /dev/null 2>&1 && type -path tput > /dev/null 2>&1;
    then
        tput rmso
    fi
}

echo ""
echo ""
echo "######################################################################"
echo "#                           Machinekit HAL                           #"
echo "#   Universal framework for machine control based on HAL principle   #"
echo "######################################################################"
echo "#                                                                    #"
echo "#   Machinekit is a universal software system for computer control   #"
echo "#   of wide spectrum of machines. Machinekit is released under the   #"
echo "#   GPL.  Check out http://www.machinekit.io for more details.       #"
echo "#                                                                    #"
echo "#                                                                    #"
echo "#   It seems that ./configure completed successfully.                #"
echo "#   If things don't work check config.log for errors & warnings      #"
echo "#                                                                    #"

if test "xyes" = "x$RUN_IN_PLACE"; then
echo "#   Next compile by typing                                           #"
echo "#         make                                                       #"
if test $with_drivers = yes ; then
echo "#         sudo make setuid                                           #"
fi
echo "#                                                                    #"
echo "#   Before running the software, set the environment:                #"
echo "#         . (top dir)/scripts/rip-environment                        #"
else
bold
echo "#   warning: If you already have an installed Machinekit, this will  #"
echo "#         replace an existing installation.  If you have installed   #"
echo "#         a machinekit package, this will damage the package.        #"
offbold
echo "#   hint: To test a self-built version of machinekit without damaging#"
echo "#         the package version, don't specify a --prefix              #"
echo "#                                                                    #"
echo "#   Next compile by typing                                           #"
echo "#         make                                                       #"
echo "#   then install it by typing                                        #"
echo "#         sudo make install                                          #"
fi
echo "#                                                                    #"
echo "#   To run the software type                                         #"
echo "#         halrun                                                     #"
echo "#                                                                    #"
echo "######################################################################"
echo ""
echo ""
